package fr.hoteia.appengine.archetype.server.web.util.impl;


import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.jstl.core.Config;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.MessageSource;
import org.springframework.web.servlet.support.RequestContextUtils;

import com.opensymphony.clickstream.Clickstream;
import com.opensymphony.clickstream.ClickstreamListener;
import com.opensymphony.clickstream.ClickstreamRequest;

import fr.hoteia.appengine.archetype.client.Constants;
import fr.hoteia.appengine.archetype.server.web.util.RequestUtil;

/**
 * <p>
 * <a href="RequestUtilImpl.java.html"><i>View Source</i></a>
 * </p>
 *
 * @author Denis GOSSET <a href="http://www.hoteia.com"><i>Hoteia.com</i></a>
 * 
 */
public class RequestUtilImpl implements RequestUtil {

    private static final Logger logger = Logger.getLogger(RequestUtilImpl.class.getName());

    private MessageSource messageSource;

    /**
     *
     */
    public String getContentLanguage(final Locale locale) {
        String country = locale.getCountry();
        String language = locale.getLanguage();
       
        if (country.equalsIgnoreCase(language)
                || StringUtils.isEmpty(country)) {
            return language;
        }

        return language + "-" + country.toLowerCase();
    }
   
    /**
     *
     */
    public String getRequestLocaleCountryCodeIso3166(final HttpServletRequest request) {

        Locale locale = request.getLocale();
        String countryCodeIso3166 = null;
        if (locale != null) {
            String countryLocale = locale.toString();
            if (countryLocale.length() > 2) {
                countryCodeIso3166 = countryLocale.substring(3, 5);
            } else {
                countryCodeIso3166 = countryLocale.substring(0, 2);
            }
        }

        return countryCodeIso3166;
    }

    /**
     *
     */
    public void handleRequestLanguage(final HttpServletRequest request, final HttpServletResponse response) {
        Locale locale = getCurrentLocale(request);
        if(locale == null){
            initRequestLocale(request, response);
        } else  {
            checkRequestLanguage(request, response);
        }
    }

    /**
     *
     */
    public Locale getCurrentLocale(final HttpServletRequest request) {
        Locale locale = (Locale) request.getSession().getAttribute(Constants.CURRENT_APPLICATION_LOCALE);
//        if (locale == null) {
//            locale = request.getLocale();
//            try {
//                if(locale.toString().length() < 3){
//                    String languageLabel = getMessageSource().getMessage("languages." + locale.toString().toUpperCase(), null, locale);
//                } else {
//                    String languageLabel = getMessageSource().getMessage("languages." + locale.getLanguage().toUpperCase(), null, locale);
//                }
//            } catch (Exception e) {
//                logger.warning("This language, " + locale.toString() + ", is not available!");
//                locale = getDefaultLocale();
//            }
//        }
        return locale;
    }

    /**
     *
     */
    private void initRequestLocale(final HttpServletRequest request, final HttpServletResponse response) {
        Locale locale = request.getLocale();
        // 1/ check URL
        String language = request.getParameter(Constants.LANGUAGE_CODE);
        if (language != null){
            locale = new Locale(language, language.toUpperCase());
            setNewRequestLanguage(request, response, locale);
        } else {
            // 2/ check request locale
            try {
                if(locale.toString().length() < 3){
                    getMessageSource().getMessage("languages." + locale.toString().toUpperCase(), null, locale);
                } else {
                    getMessageSource().getMessage("languages." + locale.getLanguage().toUpperCase(), null, locale);
                }
                locale = new Locale(locale.getLanguage(), locale.getLanguage().toUpperCase());
            } catch (Exception e) {
                logger.warning("This language, " + locale.toString() + ", is not possible!");
                locale = getDefaultLocale();
            }
        }

        setNewRequestLanguage(request, response, locale);
    }
   
    private void checkRequestLanguage(final HttpServletRequest request, final HttpServletResponse response) {
        String language = request.getParameter(Constants.LANGUAGE_CODE);
        String currentLanguage = getCurrentLanguageCode(request);
        if (language != null
                && !language.equals(currentLanguage)) {
            Locale locale = new Locale(language, language.toUpperCase());
            setNewRequestLanguage(request, response, locale);
        }
    }
   
    private void setNewRequestLanguage(final HttpServletRequest request, final HttpServletResponse response, final Locale locale) {
        if (response != null) {
            RequestContextUtils.getLocaleResolver(request).setLocale(request, response, locale);
        }
        RequestContextUtils.getLocaleResolver(request).resolveLocale(request);

        request.getSession().setAttribute(Constants.CURRENT_APPLICATION_LOCALE, RequestContextUtils.getLocale(request));
        request.getSession().setAttribute(Constants.DYNAMIC_LOCALE, getContentLanguage(locale));
        Config.set(request.getSession(), Config.FMT_LOCALE, locale);
    }
   
    /**
     *
     */
    public String getCurrentCountryCode(final HttpServletRequest request) {
        return getCurrentCountryCode(getCurrentLocale(request));
    }
   
    /**
     *
     */
    public String getCurrentCountryCode(final Locale locale) {
        String countryCode = locale.getCountry();
        if(StringUtils.isEmpty(countryCode)){
            countryCode = locale.getLanguage();
        }
        return countryCode;
    }
   
    /**
     *
     */
    public String getCurrentLanguageCode(final HttpServletRequest request) {
        Locale locale = getCurrentLocale(request);
        return locale.getLanguage();
    }
   
    /**
     *
     */
    public String getCurrentLanguageCode(final Locale locale) {
        return locale.getLanguage();
    }
   
    public String getLastRequestUrl(final HttpServletRequest request) {
        return getRequestUrl(request, 1);
    }
   
    public String getRequestUrl(final HttpServletRequest request, int position) {
       
        String url = "";
       
        final List<ClickstreamRequest> clickstreams = getClickStreamRequests(request);

        int count = 1;
        if(clickstreams != null
                && !clickstreams.isEmpty()){
            if(clickstreams != null
                    && !clickstreams.isEmpty()){
                ListIterator<ClickstreamRequest> itInversed = clickstreams.listIterator(clickstreams.size());
                while (itInversed.hasPrevious()) {
                    ClickstreamRequest clickstream = (ClickstreamRequest) itInversed.previous();
                    String uri = clickstream.getRequestURI();
                    // The last url is the current URI, so we need to get the url previous the last
                    if(count == (clickstreams.size() - position)){
                        url = uri;
                    }
                    count++;
                }
            }
        }
        return handleUrl(url);
    }
   
    @SuppressWarnings("unchecked")
    private List<ClickstreamRequest> getClickStreamRequests(final HttpServletRequest request){
        final List<ClickstreamRequest> clickstreams = getClickStream(request).getStream();
        return clickstreams;
    }
   
    private Clickstream getClickStream(final HttpServletRequest request){
        HttpSession session = ((HttpServletRequest)request).getSession();
        final Clickstream stream = (Clickstream) session.getAttribute(ClickstreamListener.SESSION_ATTRIBUTE_KEY);
        return stream;
    }
       
    private String handleUrl(String url){
        return url;
    }
   
    private Locale getDefaultLocale() {
        String localeKey = Constants.LOCALE_EN;
        return new Locale(localeKey, localeKey.toUpperCase());
    }
   
    public MessageSource getMessageSource() {
        return messageSource;
    }

    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

}